/*
 * 文件名：LuceneUtil.java	 
 * 时     间：下午8:09:07
 * 作     者：Administrator       
 * 版     权： 2012-2022 湖南智软网络科技, 公司保留所有权利.
 * 联     系：http://www.073586.com/
 */
package com.index.util;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;

import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.druid.util.StringUtils;

/**
 * 类描述:这里是类描述
 * 
 * @ClassName: LuceneUtil
 * @author Administrator
 * @date 2016年7月13日 下午8:09:07
 */
public final class LuceneSingleton implements AutoCloseable
{
	private static final Log LOG = LogFactory.getLog(LuceneSingleton.class);
	
	private static LuceneSingleton instance;
	
	private String indexFilePath = "D:/indexdata";
	
	private Directory directory;
	
	private Analyzer analyzer;
	
	private IndexWriterConfig config;
	
	private IndexWriter writer;
	
	private IndexReader reader;
	
	private IndexSearcher searcher;
	
	private LuceneSingleton(String... indexAddress) throws IOException
	{
		if (null != indexAddress && indexAddress.length > 0
				&& !StringUtils.isEmpty(indexAddress[0]))
		{
			this.indexFilePath = indexAddress[0];
		}
		this.directory = FSDirectory.open(Paths.get(this.indexFilePath));
		this.analyzer = new IKAnalyzer();
	}
	
	/**
	 * 方法描述：使用完成，请关闭操作
	 * 
	 * @Title: close
	 * @param @throws IOException
	 * @return void
	 * @user Administrator 2016年7月14日
	 * @throws
	 */
	@Override
	public void close()
	{
		try
		{
			this.reader.close();
		} catch (IOException e)
		{
			LOG.error("lucene reader close error : {}", e);
		}
//		try
//		{
//			this.writer.flush();
//		} catch (IOException e)
//		{
//			LOG.error("lucene writer flush error : {}", e);
//		}
//		try
//		{
//			this.writer.close();
//		} catch (IOException e)
//		{
//			LOG.error("lucene writer close error : {}", e);
//		}
		try
		{
			this.directory.close();
		} catch (IOException e)
		{
			LOG.error("lucene directory close error : {}", e);
		}
	}
	
	/**
	 * 方法描述：单例化lucene工具
	 * 
	 * @Title: singleton
	 * @param @param indexAddress
	 * @param @return
	 * @return LuceneSingleton
	 * @user Administrator 2016年7月14日
	 * @throws
	 */
	public static LuceneSingleton singleton(String... indexAddress)
	{
		
		try
		{
			if (null == instance)
			{
				instance = new LuceneSingleton(indexAddress);
			}
			
		} catch (IOException e)
		{
			LOG.error("LuceneSingleton error : {}", e);
		}
		return instance;
	}
	
	public void createIndex(Map<String, String> map)
	{
		try
		{
			this.config = new IndexWriterConfig(this.analyzer);
			this.writer = new IndexWriter(this.directory, this.config);
			Document doc = new Document();
			for (String key : map.keySet())
			{
				doc.add(new StringField(key, map.get(key), Field.Store.YES));
			}
			writer.addDocument(doc);
			writer.flush();
			writer.close();
		} catch (IOException e)
		{
			LOG.error("createIndex error : {}", e);
		}
	}
	
	public List<String> searchIndex(String searchKey, String searchValue,
			String resultKey)
	{
		if (null == this.reader)
		{
			try
			{
				this.reader = DirectoryReader.open(this.directory);
			} catch (IOException e)
			{
				LOG.error("DirectoryReader open error : {}", e);
			}
		}
		if (null == this.searcher)
		{
			this.searcher = new IndexSearcher(this.reader);
		}
		List<String> uuidList = new ArrayList<String>();
		// 查询车牌
		QueryParser parser = new QueryParser(searchKey, this.analyzer);
		try
		{
			Query query = parser.parse(searchValue);
			TopDocs results = this.searcher.search(query, 200);
			ScoreDoc[] hits = results.scoreDocs;
			for (int i = 0; i < hits.length; i++)
			{
				Document hitDoc = searcher.doc(hits[i].doc);
				uuidList.add(hitDoc.get(resultKey));
			}
		} catch (ParseException e)
		{
			LOG.error(searchValue + " parse error : {}", e);
		} catch (IOException e)
		{
			LOG.error(searchKey + " search error : {}", e);
		}
		return uuidList;
	}
	
	public static void main(String[] args) throws IOException, ParseException
	{
		String[] texts = new String[] { "Mybatis 分页插件 - 示例",
				"Mybatis 贴吧问答 第一期", "Mybatis 示例之 复杂(complex)属性(property)",
				"Mybatis 极其(最)简(好)单(用)的一个分页插件",
				"Mybatis 的Log4j日志输出问题 - 以及有关日志的所有问题",
				"Mybatis 示例之 foreach （下）", "Mybatis 示例之 foreach （上）",
				"Mybatis 示例之 foreach1 （上）", "Mybatis 示例之 SelectKey",
				"Mybatis 示例之 Association (2)", "Mybatis 示例之 Association" };
		
		Map<String, String> map = new HashMap<String, String>();
		for (int i = 0; i < texts.length; i++)
		{
			map.put("text" + i, texts[i]);
		}
		singleton().createIndex(map);
		List<String> list = singleton()
				.searchIndex("text0", "Mybatis", "text0");
		for (String str : list)
		{
			System.out.println(str);
		}
		singleton().close();
	}
	
	private static void test() throws IOException, ParseException
	{
		Directory directory = singleton().directory;
		// 读取索引并查询
		DirectoryReader ireader = DirectoryReader.open(directory);
		IndexSearcher isearcher = new IndexSearcher(ireader);
		// 解析一个简单的查询
		QueryParser parser = new QueryParser("fieldname", singleton().analyzer);
		Query query = parser.parse("foreach");
		ScoreDoc[] hits = isearcher.search(query, null, 1000).scoreDocs;
		// 迭代输出结果
		for (int i = 0; i < hits.length; i++)
		{
			Document hitDoc = isearcher.doc(hits[i].doc);
			System.out.println(hitDoc.get("fieldname"));
		}
		ireader.close();
		directory.close();
		
	}
}
